﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GGEditor.API.Editors;

namespace GGEditor.API.Samples.TerrainViewer
{
	public partial class View : UserControl, IEditorView
	{
		public View()
		{
			InitializeComponent();

			//OpenFileDialog ofd = new OpenFileDialog()
			//{
			//    Filter = "Warcraft II Map File (*.pud)|*.pud"
			//};
			//ofd.ShowDialog();
			//"c:\\Atols.pud"
			//FileStream file = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read);
			
			SetStyle(ControlStyles.UserPaint |
				 ControlStyles.OptimizedDoubleBuffer |
				 ControlStyles.ResizeRedraw |
				 ControlStyles.DoubleBuffer, true);

			Invalidate();
		}

		Model pud;
		private int width = 1;
		private int height = 1;

        private bool leftDown = false;
        private bool rightDown = false;
        private short activeTile = Model.LightWater;
        public short ActiveTile 
        { 
            get { return activeTile; }
            set { activeTile = value; }
        }
        private short brushRadius = 0;
        public short BrushRadius
        {
            get { return brushRadius; }
            set { brushRadius = value; }
        }

		protected float Dx
		{
			get { return Width / (float)width; }
		}

		protected float Dy
		{
			get { return Height / (float)height; }
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
			//base.OnPaintBackground(e);
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			Graphics g = e.Graphics;

			using (Brush bg = new SolidBrush(BackColor))
				g.FillRectangle(bg, ClientRectangle);


			for (int y = 0; y < height; y++)
			{
				for (int x = 0; x < width; x++)
				{
					Brush b = new SolidBrush(pud.GetColor(pud[x, y]));
					g.FillRectangle(b, x * Dx, y * Dy, Dx, Dy);
				}
			}

			//for (int y = 0; y < height; y++)
			//    g.DrawLine(Pens.White, 0, y * Dy, Width, y * Dy);

			//for (int x = 0; x < width; x++)
			//    g.DrawLine(Pens.White, x * Dx, 0, x * Dx, Height);

		}

		#region Implementation of IEditorView

		public Control Control
		{
			get { return this; }
		}

		public void SubscribeTo(IEditorModel model)
		{
			pud = model as Model;
			if (pud == null)
				throw new NullReferenceException();
			width = pud.Width;
			height = pud.Height;
			Invalidate();
		}

		public void UnsubscribeFrom(IEditorModel model)
		{
			
		}

		#endregion

        private void View_MouseUp(object sender, MouseEventArgs e)
        {
            rightDown = false;
            leftDown = false;
        }

        private void View_MouseDown(object sender, MouseEventArgs e)
        {
            int x = (int)(e.X / Dx);
            int y = (int)(e.Y / Dy);

            if (x >= 0 && x < pud.Width && y >= 0 && y < pud.Height)
            {
                if (e.Button == MouseButtons.Left)
                {
                    leftDown = true;
                    ApplyBrush(x, y);
                }
                else if (e.Button == MouseButtons.Right)
                {
                    rightDown = true;
                    ApplyBrush(x, y);
                }
            }

            Invalidate();
        }

        private void View_MouseMove(object sender, MouseEventArgs e)
        {
            if (leftDown)
            {
                int x = (int)(e.X / Dx);
                int y = (int)(e.Y / Dy);
                ApplyBrush(x, y);
            }
            if (rightDown)
            {
                int x = (int)(e.X / Dx);
                int y = (int)(e.Y / Dy);
                ApplyBrush(x, y);
            }

            Invalidate();
        }

        private void ApplyBrush(int clickX, int clickY)
        {
            int startx = clickX - BrushRadius;
            int starty = clickY - BrushRadius;
            int endx = clickX + BrushRadius;
            int endy = clickY + BrushRadius;

            for (int y = starty; y <= endy; y++)
                for (int x = startx; x <= endx; x++)
                    if (x >= 0 && x < pud.Width && y >= 0 && y < pud.Height)
                        pud[x, y] = activeTile;
        }

        private void View_KeyPress(object sender, KeyPressEventArgs e)
        {
            char key = e.KeyChar;
            char[] keyArray = { key };
            String keyString = new String(keyArray);

            if (Char.IsDigit(key))
            {
                short num = Int16.Parse(keyString);
                if(num != 0)
                    BrushRadius = (short)(num - 1);
                return;
            }
            switch (key)
            {
                case 's':
                    Console.WriteLine("Writing pud to file " + pud.FilePath);
                    pud.Save(pud.FilePath);
                    break;
                case ' ':
                    activeTile = pud.NextTool(activeTile);
                    break;
            }
        }
	}
}
